Creating and Drawing Polygons
A polygon contour is a series of points connected by straight lines. QuickDraw GX defines thegxPolygon
structure to encapsulate a polygon contour:
struct gxPolygon { long vectors; struct gxPoint vector[gxAnyNumber]; };Thevectors
field indicates the number of points in the polygon and thevector
array contains the points themselves. (The constantgxAnyNumber
is used as a placeholder, since a polygon contour can have any number of geometric points.)The polygon shape type allows you to group any number of polygon contours within a single QuickDraw GX shape. The
gxPolygons
structure encapsulates the multiple-polygon geometry:
struct gxPolygons { long contours; struct gxPolygon contour[gxAnyNumber]; };Thecontours
field indicates the total number of contours (in other words, the total number of separate polygons), and thecontour
array contains the polygon contour geometries.
- Implementation Note
- In version 1.0 of QuickDraw GX, a single path contour can have between 0 and 32,767 geometric points. The geometry of a path shape can between 0 and 32,767 polygon contours. The total size of a path geometry may not exceed 2,147,483,647 bytes.
![]()
Creating Polygons With a Single Contour
Since agxPolygons
structure is of variable length and every element in it is of typelong
, you can define a polygon geometry as an array of long values. For example, the definition
long aPolygonGeometry[] = {1, /* number of contours */ 3, /* number of points */ ff(50), ff(50), ff(100), ff(80), ff(50), ff(110)};defines a polygon geometry with one contour (that is, with one polygon). The polygon contains three points; it is a triangle.Most QuickDraw GX functions that create or draw polygon shapes expect a pointer to a
gxPolygons
structure as one of the parameters. Therefore, you must cast an array of long values to the correct type before sending it to one of these functions. As an example, you can cast theaPolygonGeometry
array to the correct type with this expression:
(gxPolygons *) aPolygonGeometryThe sample function in Listing 2-12 shows how to use this geometry to draw a triangle.Listing 2-12 Drawing a triangular polygon
void DrawTriangle(void) { static long aPolygonGeometry[] = {1, /* number of contours */ 3, /* number of points */ ff(50), ff(50), ff(100), ff(80), ff(50), ff(110)}; GXDrawPolygons((gxPolygons *) aPolygonGeometry, gxEvenOddFill); }This sample function defines theaPolygonGeometry
array, casts it to agxPolygons
pointer, and sends it to theGXDrawPolygons
function. Unlike theGXDrawPoint
,GXDrawLine
,GXDrawCurve
, andGXDrawRectangle
functions, theGXDrawPolygons
function takes a second parameter--the shape fill to use when drawing the polygon shape. In this example, the parameter is set to the even-odd shape value and the resulting polygon is shown in Figure 2-25.
You can specify any type of shape fill for polygon shapes. For example, if you specify the inverse even-odd shape fill:
GXDrawPolygons((gxPolygons *) aPolygonGeometry, gxInverseEvenOddFill);QuickDraw GX draws the graphic shown in Figure 2-26. The black portion of the drawing would be clipped according to the information in the default polygon shape's transform object. If no clipping information is specified there, the drawing would extend to the full range of the shape's view port.Figure 2-26 A triangular polygon with inverse shape fill
For information on clipping and view ports, see Inside Macintosh: QuickDraw GX Objects.
Although this example draws the polygon without creating a polygon shape, it could instead create a polygon shape with the
GXNewPolygons
function:
aPolygonShape = GXNewPolygons((gxPolygons *) aPolygonGeometry);and then draw it using theGXDrawShape
function:
GXDrawShape(aPolygonShape);You can also create polygon shapes using theGXNewShape
function:
aPolygonShape = GXNewShape(gxPolygonType); GXSetPolygons(aPolygonShape, (gxPolygons *) aPolygonGeometry);or by using theGXNewShapeVector
function:
aPolygonShape = GXNewShapeVector(gxPolygonType, aPolygonGeometry);Notice that in this case you do not have to cast theaPolygonGeometry
array to be a pointer to agxPolygons
structure. TheGXNewShapeVector
function expects an array of long values.Although the
GXDrawPolygons
function (shown in Listing 2-12) allows you to specify a shape fill, theGXDrawShape
function does not. If you create a polygon shape and you want it to have a different shape fill than the default polygon shape, you must indicate the desired shape fill using theGXSetShapeFill
function--for example,
GXSetShapeFill(aPolygonShape, gxInverseEvenOddFill);For more information about shape fills, see "Shape Fill" beginning on page 2-12.Creating Polygons With Multiple Contours
The sample function in Listing 2-13 shows how a single polygon shape can contain more than one polygon contour. The polygon shape defined in this example includes the triangle from the previous example as well as a second, entirely separate, triangle.Listing 2-13 Creating a polygon with two contours
void DrawTwoTriangles(void) { gxShape aPolygonsShape; static long aPolygonsGeometry[] = {2, /* number of contours */ 3, /* number of points */ ff(50), ff(50), ff(100), ff(80), ff(50), ff(110), 3, /* number of points */ ff(200), ff(50), ff(150), ff(80), ff(200), ff(110)}; aPolygonsShape = GXNewPolygons((gxPolygons *) aPolygonsGeometry); GXDrawShape(aPolygonsShape); GXDisposeShape(aPolygonsShape); }This sample function results in the drawing shown in Figure 2-27.Figure 2-27 A filled polygon with two separate contours
For more information about polygon shapes and multiple contours, see "Polygon Shapes" beginning on page 2-22.
Creating Polygons With Crossed Contours
Since a polygon contour is defined as an array of geometric points connected by straight lines, it is possible for the lines that make up a polygon contour to cross over each other. The sample function in Listing 2-14 creates such a polygon.Listing 2-14 Creating a polygon with a crossed contour
void CreateCrossedContour(void) { gxShape aPolygonsShape; static long aPolygonsGeometry[] = {1, /* number of contours */ 4, /* number of points */ ff(50), ff(50), ff(150), ff(110), ff(150), ff(50), ff(50), ff(110)}; aPolygonsShape = GXNewPolygons((gxPolygons *) aPolygonsGeometry); GXSetShapeFill(aPolygonsShape, gxClosedFrameFill); GXDrawShape(aPolygonsShape); GXDisposeShape(aPolygonsShape); }Figure 2-28 shows the geometry of the resulting polygon contour as well as how the contour appears when drawn with the closed-frame shape fill.Figure 2-28 A framed polygon with a crossed contour
You can change the shape fill of this polygon by removing this line of code from the sample function in Listing 2-14:
GXSetShapeFill(aPolygonsShape, gxClosedFrameFill);If you don't specify a shape fill, theGXNewPolygons
function uses the shape fill from the default polygon, which is the even-odd shape fill (unless you change it using theGXGetDefaultShape
andGXSetShapeFill
functions). The polygon resulting from an even-odd shape fill is shown in Figure 2-29.Figure 2-29 A solid polygon with a crossed contour
Notice that QuickDraw GX fills both sections of this polygon.
It is possible to create a polygon with a contour that overlaps in such a way that QuickDraw GX does not fill all sections of the polygon. The sample function in
Listing 2-15 creates such a polygon.Listing 2-15 Creating a polygon with an overlapping contour
void CreateOverlappingContour(void) { gxShape aPolygonShape; static long aPolygonGeometry[] = {1, /* number of contours */ 6, /* number of points */ ff(50), ff(50), ff(100), ff(80), ff(25), ff(150), ff(25), ff(10), ff(100), ff(80), ff(50), ff(110)}; aPolygonShape = GXNewPolygons((gxPolygons *) aPolygonGeometry); GXSetShapeFill(aPolygonShape, gxHollowFill); GXDrawShape(aPolygonShape); GXDisposeShape(aPolygonShape); }Figure 2-30 shows the geometry of the resulting polygon contour as well as how the contour appears when drawn with the closed-frame shape fill.Figure 2-30 A polygon with an overlapping contour and closed-frame shape fill
If you specified the even-odd shape fill for this polygon, instead of the closed-frame shape fill, the resulting shape would appear as in Figure 2-31.
Figure 2-31 A polygon with an overlapping contour and even-odd shape fill
Notice that QuickDraw GX fills in the polygon but does not fill in the area contained in the inner loop. The algorithm used by QuickDraw GX to fill in shapes with the even-odd shape fill doesn't fill loops within the shape. (It would, however, fill another loop inside the first loop.)
The winding shape fill works differently. If you specify the winding shape fill for this polygon using the call
GXSetShapeFill(aPolygonShape, gxWindingFill);QuickDraw GX draws the polygon as shown in Figure 2-32.Figure 2-32 A polygon with an overlapping contour and winding shape fill
As you can see, the winding shape fill causes QuickDraw GX to hide the inner loop--it fills in the entire polygon, outer loop and inner.
It is possible, however, to define a polygon in such a way that QuickDraw GX does not fill the inner loop even when you specify the winding shape fill. Unlike the even-odd shape fill, which never fills an inner loop, winding shape fill considers contour direction when filling a shape:
For more information about contour direction and shape-filling algorithms, see "Shape Fill" beginning on page 2-12.
- If the inner loop and the outer loop have the same contour direction, winding shape fill causes QuickDraw GX to fill the inner loop as well as the outer loop, as shown in Figure 2-32.
- If the inner loop and the outer loop have opposite contour directions, winding shape fill causes QuickDraw GX to fill the outer loop, but not the inner loop. The next section gives an example using path shapes.
For more information about polygon shapes, see "Polygon Shapes" on page 2-22 and "Polygon Structures" on page 2-106.
For information about the functions you can use to create and draw polygons, see the description of the
GXNewPolygons
function on page 2-116 and theGXDrawPolygons
function on page 2-161.
Main | Page One | What's New | Apple Computer, Inc. | Find It | Contact Us | Help